package com.example.springbootdemo.config;

import com.example.springbootdemo.constant.BaseException;
import com.example.springbootdemo.constant.Result;
import com.example.springbootdemo.constant.annotation.ApiResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.Objects;

/**
 * @author Gong.Yang
 */
@Slf4j
@Order(0)
@ResponseBody
@ControllerAdvice
public class GlobeControllerAdvice implements ResponseBodyAdvice {
    /**
     * 统一异常
     */
    @ExceptionHandler(value = BaseException.class)
    @ResponseStatus(HttpStatus.OK)
    public Result waringExcection(BaseException e) {
        return Result.form(e.getCode(), null, e.getMsg());
    }


    /**
     * 所有接口请求成功后的返回值都要在这里包装成统一格式
     */
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
                                  Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {

        ApiResult methodAnnotation = returnType.getMethodAnnotation(ApiResult.class);

        if (Objects.isNull(methodAnnotation)) {
            return Result.form("200", body, null);
        }
        if (!methodAnnotation.enable()) {
            return body;
        }

        return Result.form(methodAnnotation.successCode(), body, methodAnnotation.successMsg());
    }

    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return (!resultIsString(converterType))
                && (!resultIsReuslt(returnType));
    }

    private boolean resultIsString(Class converterType) {
        return converterType.equals(StringHttpMessageConverter.class);
    }

    private boolean resultIsReuslt(MethodParameter returnType) {
        Class<?> clazz = returnType.getParameterType();
        return clazz.equals(Result.class);
    }

}
